<?php
// @formatter:off
/**
 * @file WCSessionKeep.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-08-05 00:26:28 +0000 (Mon, 05 Aug 2013) $
 *
 * $Id: WCSessionKeep.php 100 2013-08-05 00:26:28Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0.0.1/includes/security/WCSessionKeep.php $
 */
// @formatter:on

/**
 * @class WCSessionKeep This class is the representation of a session keeper.
 * A session keeper is an mechanism made as a combination of database an cookie
 * in order to keep a user session, even if it closes the browser.
 */
class WCSessionKeep extends WCTableRepresentation {
	/**
	 * @var string[] This variable holds the list of columns that cannot be
	 * directly modified by the pseudo-method __set().
	 * In this case skp_id.
	 */
	protected $_PropertiesReadOnly = array("id");
	/**
	 * @var string This is the prefix of every column on the table
	 * '%session_keeps'.
	 */
	protected $_PropertiesPrefix = "skp_";
	/**
	 * @var string This is the name of the represented table. In this case,
	 * '%session_keeps'.
	 */
	protected $_PropertiesTable = "session_keeps";
	/**
	 * @var string This is a piece of query that will be used when a row of
	 * '%session_keeps' is updated.
	 */
	protected $_PropertiesAutoSet = ", skp_timestamp = sysdate()";
	//
	// Public methods.
	/**
	 * This method allows to get the last user that logged-in from a browser
	 * based on its cookies.
	 *
	 * @return WCUser Returns a pointer to the last logged-in user. Otherwise
	 * returns null.
	 */
	public function lastUser() {
		//
		// Setting a default value to be returned.
		$out = null;
		//
		// Checking if there's a user cookie.
		if(isset($_COOKIE[WC_COOKIE_KEEPME_USER])) {
			//
			// Loading global pointers.
			global $wcUsersHolder;
			//
			// Loading user information.
			$out = $wcUsersHolder->item($_COOKIE[WC_COOKIE_KEEPME_USER]);
			//
			// Checking user status.
			if(!$out || !$out->ok()) {
				//
				// At this point, user has issues, therefore,
				// null is returned
				$out = null;
			}
		}
		//
		// Returning found user.
		return $out;
	}
	/**
	 * This method attempts to load a session based on cookies in user's
	 * current browser.
	 *
	 * @return boolean Returns true the the session is valid.
	 */
	public function loadByCookies() {
		//
		// Setting internal status to false.
		$this->_ok = false;
		//
		// Cleaning internal information.
		$this->_info = array();
		//
		// Getting current IP address.
		$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "unknown";
		//
		// Creating a statement to load an specific session keeper.
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  *\n";
			$query .= "from    {$this->_dbprefix}session_keeps\n";
			$query .= "where   skp_user = :user\n";
			$query .= " and    skp_ip   = :ip\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}
		//
		// Building database parameters.
		$params = array(
			":user" => @$_COOKIE[WC_COOKIE_KEEPME_USER],
			":ip" => $ip
		);
		//
		// Searching session keeper.
		if($stmt->execute($params)) {
			//
			// Searching a session keeper taht matches user, IP
			// address, salt and tasty code.
			foreach($stmt->fetchAll() as $row) {
				if($row["skp_code"] == WCSessionKeep::CodeGenertor($row["skp_salt"])) {
					//
					// At this point a matching session keeper
					// was found, therefore it is loaded.
					$this->load($row["skp_id"]);
					//
					// Search ends here.
					break;
				}
			}
		}
		//
		// Returning final loading status.
		return $this->ok();
	}
	/**
	 * This method updates browser's cookies with current values.
	 */
	public function updateCookies() {
		//
		// Checking if this keeper has issues.
		if($this->ok()) {
			//
			// Loading global pointers.
			global $wcUsersHolder;
			//
			// Calculating until when a cookie can live.
			$lifetime = time() + (86400 * 7);
			//
			// Updating user id cookie.
			setcookie(WC_COOKIE_KEEPME_USER, $this->user, $lifetime);
			//
			// Updating cross session hash code cookie.
			setcookie(WC_COOKIE_KEEPME_HASH, $this->code, $lifetime);
			//
			// Loading full user information.
			$aux = $wcUsersHolder->item($this->user);
			if($aux && $aux->ok()) {
				//
				// Saving current user name in a cookie for the
				// future.
				setcookie(WC_COOKIE_KEEPME_NAME, $aux->name(), $lifetime);
			}
		}
	}
	//
	// Public class methods.
	/**
	 * This method creates a tasty hash code based on some session
	 * information and a little bit of salt :) .
	 *
	 * @param string $salt A little bit of salt to create a unique code.
	 * @return string Returns a tasty hash code.
	 */
	public static function CodeGenertor($salt) {
		//
		// Current user IP address will be part of the code.
		$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "unknown";
		//
		// Creating a salty code using IP address and current browser name.
		$code = $salt.$ip.$salt.$_SERVER["HTTP_USER_AGENT"].$salt;
		//
		// Returning a code.
		return md5($code);
	}
}
?>